Informatio

Visual Form

Design is a requirement, not a cosmetic addition. (nature methods)

  • Nützlichkeit
  • Effizienz
  • Ästhetik

Foto von Samuel Scrimshaw auf Unsplash

Nützlichkeit

Foto von Kelly Sikkema auf Unsplash
Foto von Yucel Moran auf Unsplash

Hier gilt ganz besonders: Simplify to Clarify

Funktionelles Design

Foto von BVG

Foto von BVG

Dabei kann es helfen, sich von bereits vorhandenen Plots inspirieren zu lassen.
Handschriftliche Skizze ist auch erstmal hilfreich!

Simplify to clarify: Data-ink ratio

Data graphics should draw the viewer’s attention to the sense and substance of the data, not to something else. (Tufte & Graves-Morris, 1983)

Auf die Spitze getrieben von Tufte & Graves-Morris (1983):

Data-ink ratio = Data-ink / Total ink used to print the graphic

  • Jedes Stück Tinte sollte einen Grund haben.

:::{.image-ref} CC BY-SA 2.0, Link

:::

Data-ink ratio in Praxis

10% Daten, 90 % Achsenbeschriftungen und Hintergrundlinien

library(ggthemes)

ggplot(
  data = gapminder_2020,
  mapping = aes(x = gini, y = hapiscore_whr, color = world_4region)
) +
  geom_point() +
  theme_excel() +
  scale_x_continuous(
    breaks = scales::pretty_breaks(n = 10), # ensure ticks
    minor_breaks = waiver() # ensures minor ticks too
  ) +
  scale_y_continuous(
    breaks = scales::pretty_breaks(n = 10),
    minor_breaks = waiver()
  ) +
  theme(
    panel.grid.major = element_line(color = "grey60", size = 1.2), # thick major grid
    panel.grid.minor = element_line(color = "grey60", size = 0.8) # thick minor grid
  )

0% Daten (Plotte die Daten, keine Zusammenfassungen)

ggplot(
  data = gapminder_2020,
  mapping = aes(x = gini, y = hapiscore_whr, color = world_4region)
) +
  geom_smooth()

ca. 90 % Daten, 10 % Achsenbeschriftungen und Legende

library(ggthemes)
ggplot(
  data = gapminder_2020,
  mapping = aes(x = gini, y = hapiscore_whr, color = world_4region)
) +
  geom_point() +
  theme_tufte()

Redundanzen

Erase non-data-ink, within reason. Erase redundant data-ink, within reaseon (Tufte & Graves-Morris, 1983)

Auf wie viele Arten wird hier die Höhe der CO2 Emissionen pro Kopf dargestellt?

Auf sieben verschiedene Arten:

  1. Höhe der linken Balkenlinie
  2. Höhe der rechten Balkenlinie
  3. Höhe der horizontalen Balkenlinie
  4. Höhe des Balkeninneren
  5. Farbe des Balkens
  6. Position des Labels
  7. Wert des Labels

Balken an sich enthalten also schon redundante Informationen!

Entferne alle Redundanzen, machen den Plot also “Tufte-Komform”

ggplot(
  gapminder_2020[1:10, ],
  aes(x = reorder(country, co2_pcap_cons), y = co2_pcap_cons, fill = co2_pcap_cons, color = co2_pcap_cons, label = round(co2_pcap_cons), 2)
) +
  geom_bar(stat = "identity", width = 1, color = "black") +
  geom_text(vjust = -1, color = "black") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
  labs(
    x = "Land",
    y = "CO2 Consumption per capita in t") +
  theme_bg()

Entfernen der Achsenlinien und Umrandungen. Hintergrundlinien werden innerhalb der Balken dargestellt.

Mitunter können die vertikalen und horizontalen Linien auch hilfreich beim Vergleich/bei der Zuordnung zum Land sein: “Tufte Barchart”

Maximieren von Informationen

Normaler Scatterplot

Box um den Plot, Grid-Linien, Achsen-Ticks: Alles keine Daten.

ggplot(
  data = gapminder_2020,
  mapping = aes(x = gini, y = hapiscore_whr, color = world_4region)
) +
  geom_point() 

Tufte-Scatterplot

Nutzen der Ticks und Achsen-Linien, um Informationen zu transportieren.

library(paletteer)


xlim_v <- c(20, 80)
ylim_v <- c(20, 80)

# Parameter: Anzahl der Quantile, Versatz von den Rändern, kleine Lücke zwischen Segmenten
probs <- seq(0, 1, by = 0.25) # Quartile; für Dezile: by = 0.1
off_x <- 0 # Versatz der "y-Achse" nach rechts
off_y <- 0 # Versatz der "x-Achse" nach oben
gap <- 0.2 # kleine Lücke an Segmentenden (optisch schöner)

qx <- quantile(gapminder_2020$gini, probs = probs, na.rm = TRUE)
qy <- quantile(gapminder_2020$hapiscore_whr, probs = probs, na.rm = TRUE)

# Segment-Dataframes bauen (pro Intervall ein Segment)
seg_x <- tibble(
  x    = pmax(qx[-length(qx)] + gap / 2, xlim_v[1]),
  xend = pmin(qx[-1] - gap / 2, xlim_v[2]),
  y    = ylim_v[1] + off_y,
  yend = ylim_v[1] + off_y
) %>% filter(x < xend)

seg_y <- tibble(
  x    = xlim_v[1] + off_x,
  xend = xlim_v[1] + off_x,
  y    = pmax(qy[-length(qy)] + gap / 2, ylim_v[1]),
  yend = pmin(qy[-1] - gap / 2, ylim_v[2])
) %>%
  filter(y < yend)

ggplot(
  data = gapminder_2020,
  mapping = aes(x = gini, y = hapiscore_whr, color = world_4region)
) +
  geom_point() +
  # Quantil-"x-Achse" (horizontal) leicht ins Panel versetzt
  geom_segment(
    data = seg_x,
    aes(x = x, xend = xend, y = y, yend = yend),
    inherit.aes = FALSE
  ) +
  # Quantil-"y-Achse" (vertikal) leicht ins Panel versetzt
  geom_segment(
    data = seg_y,
    aes(x = x, xend = xend, y = y, yend = yend),
    inherit.aes = FALSE
  ) +
  scale_x_continuous(breaks = unique(c(round(seg_x$x, 0), round(seg_x$xend, 0)))) +
  scale_y_continuous(breaks = unique(c(round(seg_y$y, 0), round(seg_y$yend, 0)))) +
  coord_cartesian(xlim = xlim_v, ylim = ylim_v, expand = FALSE) +
  theme_tufte() +
  theme(axis.ticks = element_blank()) +
  paletteer::scale_colour_paletteer_d("fishualize::Koumansetta_rainfordi")

Verteilungen Plotten




Reduzieren heißt nicht, die Informationen zu reduzieren, sondern den Chart-Junk!
Sehr oft macht es Sinn, die gesamte Verteilung zu plotten, möglicherweise auch zusätzlich zu zusammenfassenden Statistiken.

Verteilungen plotten

Boxplot

ggplot(data = gapminder_2020 %>% drop_na(country),
  aes(x = world_4region, y = hapiscore_whr, fill = world_4region)) +
  geom_boxplot() +
  theme(axis.ticks = element_blank(), legend.position = "none") +
  scale_fill_paletteer_d("fishualize::Koumansetta_rainfordi") +
  xlab("Region") +
  ylab("Happiness Score (World Happiness Report)")

Tufte-Boxplot

library(ggthemes)

ggplot(data = gapminder_2020 %>% drop_na(country), 
  aes(x = world_4region, y = hapiscore_whr, group = world_4region)) +
geom_jitter(alpha = 0.5, color = "lightgrey") + 
  geom_tufteboxplot() +
  scale_fill_paletteer_d("fishualize::Koumansetta_rainfordi") +
  xlab("Region") +
  ylab("Happiness Score (World Happiness Report)") +
theme_tufte()

Keine Angst vor leerem Raum

Zusammenfassung



  1. Above all else show the data.
  2. Maximize the data-ink ratio, within reason.
  3. Erase non-data-ink, within reason.
  4. Erase redundant data-ink, within reason.
  5. Revise and edit.

Aus Tufte & Graves-Morris (1983).

Gegenentwurf: Ästhetik

Abbildung von [Cédric Scherer]https://www.behance.net/gallery/100683383/Travelling-to-Outer-Space#).

Wandelt euren Plot in einen Tufte-Plot um.

Farben als Design-Element

All colors are the friends of their neighbors and the lovers of their opposites. - Marc Chagall

Nach MalteAhrens at de.wikipedia. Vectorization by User:SidShakal - Raster version from Wikimedia Commons., Gemeinfrei, Link

Kleine Farbenlehre

Vincent van Gogh, Public domain, via Wikimedia Commons

  • Gegenüberliegende Farben intensivieren sich gegenseitig: eine Primärfarbe, und eine Sekundärfarbe, die aus den anderen beiden Primärfarben gemischt wird. Das erzeugt stärkere Kontraste. (Van Gogh bild)
  • Mit weiß und schwarz lassen sich die Schattierungen hinzumischen
  • triadisches Farbschema: Fom MIttelpunkt des Farbkreises Strahlen mit gleichem Winkel abgehen lassen (So viele, wie man Farben haben will). Das wählt dann Farben mit dem größten Kontrast aus. (https://www.kunstplaza.de/fashion-design/farbenlehre-farbtheorie-styleguides-fashion-design/)

Weitere Tools

Wollbox von Vincent van Gogh, mit der er Farbkombinationen getestet hat. Eigenes Bild.

Schriften

Die Schriftart kann einer Abbildung ein ganz anderes Aussehn vereleihen.
Wir nutzen Schriftarten von Google Fonts

library(showtext)

font_add_google("Special Elite", family = "special")

Daten von zygmuntz.

library(ggwordcloud)

tags <- read.csv(here::here("data", "goodbooks-10k", "tags.csv"))
book_tags <- read.csv(here::here("data", "goodbooks-10k", "book_tags.csv"))
books <- read.csv(here::here("data", "goodbooks-10k", "books.csv")) 


classics <- book_tags %>% 
left_join(books) %>%
left_join(tags) %>% 
filter(tag_name == "classics") %>% 
filter(ratings_count > 20000, !duplicated(authors)) %>%
  select(original_title, average_rating, tag_name, ratings_count) %>%
  distinct() %>% 
  arrange(ratings_count) %>%
  slice_tail(n = 50)


set.seed(45)
ggplot(data = classics, 
       mapping = aes(label = original_title, size = average_rating)) +
  geom_text_wordcloud() +
scale_size(range = c(1, 6)) +
labs(title = "What to read next ...", 
subtitle = "... according to goodreads") +
theme_bg()

font_add_google("Special Elite", family = "my textfont")
font_add_google("Playfair Display")

showtext_auto()


set.seed(45)
ggplot(data = classics, 
       mapping = aes(label = original_title, size = average_rating)) +
  geom_text_wordcloud(family = "my textfont") +
scale_size(range = c(1, 6)) +
labs(title = "What to read next", 
subtitle = "According to goodreads") +
theme_bg() +
theme(title = element_text(family = "Playfair Display", size = 20), 
)

Suche dir eine Schriftart aus Google Fonts und baue sie in deinen Plot ein.

Übung

Wähle eine Grafik von … aus und erstelle einen Plan, wie du sie verbessern würdest.

Tufte, E. R., & Graves-Morris, P. R. (1983). The visual display of quantitative information (Bd. 2). Graphics press Cheshire, CT.